package com.fubon.wloan.controller;

import com.alibaba.fastjson.JSON;
import com.fubon.wloan.pojo.Trans;
import com.fubon.wloan.pojo.Body;
import com.fubon.wloan.pojo.CreditQueryResp;
import com.fubon.wloan.pojo.CreditResp;
import com.fubon.wloan.pojo.Expanding;
import com.fubon.wloan.pojo.InvestInfo;
import com.fubon.wloan.pojo.InvestResp;
import com.fubon.wloan.pojo.LoanBasicInfo;
import com.fubon.wloan.pojo.LoanRespBasicInfo;
import com.fubon.wloan.pojo.Msg;
import com.fubon.wloan.pojo.PersonInfo;
import com.fubon.wloan.pojo.Relas;
import com.fubon.wloan.pojo.Resp;
import com.fubon.wloan.service.ConsumeService;
import com.fubon.wloan.service.CreditService;
import com.fubon.wloan.service.InvestService;
import com.fubon.wloan.service.TransService;
import com.fubon.wloan.util.CryptoUtil;
import com.fubon.wloan.util.DateUtil;
import com.fubon.wloan.constant.TradeNo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/api")
public class RxCreditController {

    @Autowired
    TransService transService;

    @Autowired
    CreditService creditService;

    @Autowired
    ConsumeService consumerService;

    @Autowired
    InvestService investService;

    @PostMapping(value = "/route")
    public Mono<Trans> ApiRoute(@RequestBody Trans msg) {
        Mono<Trans> res = null;
        Trans trans = CryptoUtil.decode(msg);
        String tradeNo = JSON.parseObject(trans.getData(),Msg.class).getHeader().getTradeNo();
        switch (tradeNo){
            //同步响应
            case TradeNo.CREDIT_DECSION:
                res = SaveCredit(trans);
                break;
            case TradeNo.CREDICT_QUERY:
                res = findCredit(trans);
                break;
            case TradeNo.COST_CREDICT:
                res = SaveConsumer(trans);
                break;
            case TradeNo.COST_CREDICT_QUERY:
                res = findConsumer(trans);
                break;
            case TradeNo.INVES_DECSION:
                res = SaveConsumer(trans);
                break;
            case TradeNo.INVES_QUERY:
                res = findConsumer(trans);
                break;
            //回调用
            // case TradeNo.CREDIT_CALLBACK:
            //     res = creditCallBack(trans);
            //     break;
            // case TradeNo.COST_CREDICT_CALLBACK:
            //     res = CostCallBack(trans);
            //     break;
            // case TradeNo.INVES_CALLBACK:
            //     res = InvestCallBack(trans);
            //     break;    

        }
        return res;
    }

    @PostMapping(value = "/SaveCredit")
    public Mono<Trans> SaveCredit(@RequestBody Trans trans) {
        Msg<PersonInfo, Relas> msg = transService.parseByType(trans);
        Mono<Trans> res = transService.SaveCreditReqToCouchbase(msg);
        creditService.SaveCreditData((msg.getBody())).subscribe();
        creditService.SendCallbackMsg(msg.getBody()).subscribe();
        return res;
    }

    @PostMapping(value = "/findCredit")
    public Mono<Trans> findCredit(@RequestBody Trans trans) {
        Msg<Void, Void> msg = transService.parseByType(trans);
        String reqSn = msg.getBody().getReqSn();
        Mono<CreditResp> resp = creditService.findByReqSn(reqSn);

        return resp
                .map(basic -> CreditQueryResp.builder().reqSn(reqSn).retCode("0")
                        .timestamp(DateUtil.getCurrentTimeString()).basicInfo(basic).build())
                .map(transRes -> CryptoUtil
                        .encode(Trans.builder().icode("xxxx").data(JSON.toJSONString(transRes)).build()));
    }

    @PostMapping(value = "/SaveConsumer")
    public Mono<Trans> SaveConsumer(@RequestBody Trans trans) {

        Msg<LoanBasicInfo,Expanding> msg = transService.parseByType(trans);
        Mono<Trans> res = transService.SaveConsumeReqToCouchbase(msg);
        consumerService.SaveCreditData((msg.getBody())).subscribe();
        consumerService.SendCallbackMsg((msg.getBody())).subscribe();
        return res;

    }

    @PostMapping(value = "/findConsumer")
    public Mono<Trans> findConsumer(@RequestBody Trans trans) {
        Msg<Void, Void> msg = transService.parseByType(trans);
        String reqSn = msg.getBody().getReqSn();
        Mono<LoanRespBasicInfo> resp = consumerService.findByReqSn(reqSn);

        return resp
                .map(basic -> CreditQueryResp.builder().reqSn(reqSn).retCode("0")
                        .timestamp(DateUtil.getCurrentTimeString()).basicInfo(basic).build())
                .map(transRes -> CryptoUtil
                        .encode(Trans.builder().icode("xxxx").data(JSON.toJSONString(transRes)).build()));
    }

    @PostMapping(value = "/SaveInvest")
    public Mono<Trans> saveInvest(@RequestBody Trans trans) {
        Msg<InvestInfo, Expanding> msg = transService.parseByType(trans);
        Mono<Trans> res = transService.SaveCreditReqToCouchbase(msg);
        investService.SaveData((msg.getBody())).subscribe();
        investService.SendCallbackMsg(msg.getBody()).subscribe();
        return res;
    }

    @PostMapping(value = "/findInvest")
    public Mono<Trans> findInvest(@RequestBody Trans trans) {
        Msg<Void, Void> msg = transService.parseByType(trans);
        String reqSn = msg.getBody().getReqSn();
        Mono<InvestResp<Expanding>> resp = investService.findByReqSn(reqSn);

        return resp
                .map(expanding -> InvestResp.builder().reqSn(reqSn).retCode("0")
                        .timestamp(DateUtil.getCurrentTimeString()).expanding(expanding).build())
                .map(transRes -> CryptoUtil
                        .encode(Trans.builder().icode("xxxx").data(JSON.toJSONString(transRes)).build()));
    }


    @PostMapping(value = "/replytest")
    public Mono<CreditResp> replytest(@RequestBody Body<PersonInfo, Relas> body) {
        CreditResp resp = new CreditResp("reqSn", "risCode", "reason", "reasonMsg", "lmtNo", 9, "startDt",
                "startDt");
        System.out.println(resp.toString());
        return Mono.just(resp);

    }

    @PostMapping(value = "/callback")
    public Mono<Trans> callback(@RequestBody Trans trans) {
        
        Trans resp = Trans.builder().icode("xxxx").data(JSON.toJSONString(new Resp("reqSn", "retCode"))).build();
        System.out.println(resp.toString());
        return Mono.just(CryptoUtil.encode(resp));

    }

}